/*******************************************************************************
BallEntity.cpp

Notes:
*******************************************************************************/

#include "BallEntity.h"

const std::string BallEntity::Type = "Ball";

BallEntity::BallEntity(EntityResource& entityData)
{
	srand((unsigned int)time(0));

	// Store the width and height
	m_width = (float)atoi(entityData.GetProperty("Width").c_str());
	m_height = (float)atoi(entityData.GetProperty("Height").c_str());
	// Store the initial speed of the ball and the increment factor
	m_fSpeed = (float)atoi(entityData.GetProperty("Speed").c_str());
	m_fInitialSpeed = m_fSpeed;
	m_fSpeedFactor = (float)atoi(entityData.GetProperty("SpeedFactor").c_str());

	InitializeDirection();

	// This is not a boundary
	m_isBounds = false;
} // BallEntity

void BallEntity::Update(float fElapsed)
{
	// Change the position of the ball
	m_x += (m_fSpeed * m_fXFactor) * fElapsed;
	m_y += (m_fSpeed * m_fYFactor) * fElapsed;

	// Check for any collisions
	Entity* pEntity = Physics::CheckForCollision(this);

	// If we have collided ...
	if(NULL != pEntity)
	{
		// If the entity we've collided with is a boundary ...
		if(pEntity->IsBounds())
		{
			// ... detect which side we went off of and adjust accordingly

			// top
			if(m_y < pEntity->GetY())
			{
				m_y = pEntity->GetY();
				m_fYFactor *= -1;
			} // if

			// bottom
			if(m_y + m_height > pEntity->GetY() + pEntity->GetHeight())
			{
				m_y = (pEntity->GetY() + pEntity->GetHeight()) - m_height;
				m_fYFactor *= -1;
			} // if

			// left
			if(m_x < pEntity->GetX())
			{
				static_cast<LevelEntity*>(pEntity)->AddPoint(true);
				m_x = (pEntity->GetWidth() / 2.0f) - (m_width / 2.0f);
				m_y = (pEntity->GetHeight() / 2.0f) - (m_height / 2.0f);
				m_fSpeed = m_fInitialSpeed;
				InitializeDirection();
			} // if

			// right
			if(m_x + m_width > pEntity->GetX() + pEntity->GetWidth())
			{
				static_cast<LevelEntity*>(pEntity)->AddPoint(false);
				m_x = (pEntity->GetX() + pEntity->GetWidth() / 2.0f) - (m_width / 2.0f);
				m_y = (pEntity->GetY() + pEntity->GetHeight() / 2.0f) - (m_height / 2.0f);
				m_fSpeed = m_fInitialSpeed;
				InitializeDirection();
			} // if
		} // if
		// otherwise, we've hit a paddle
		else
		{
			// Increase the speed
			m_fSpeed += m_fSpeedFactor;

			// Adjust angle depending on which part of the paddle you hit. 

			// Find the new y portion based on the percent
			float paddleHeight = pEntity->GetHeight();
			float paddleY = pEntity->GetY();
			float relY = m_y + (m_height / 2.0f) - paddleY;
			float newYFactor = ((relY / paddleHeight) - 0.5f);

			// Change the x and y factors and keep them normalized
			m_fYFactor = newYFactor;
			float oldXFactor = m_fXFactor;
			m_fXFactor = 1.0f - abs(m_fYFactor);
			// If we were going to the right, make sure we're going to the left now
			if(oldXFactor > 0)
			{
				m_fXFactor *= -1;
			}
			
			// Move so the ball isn't inside the paddle.

			// left paddle
			if(oldXFactor < 0)
			{
				m_x = pEntity->GetX() + pEntity->GetWidth();
			} // if
			// right paddle
			else
			{
				m_x = pEntity->GetX() - m_width;
			} // else
		} // else
	} // if
} // Update

void BallEntity::InitializeDirection()
{
	// Generate a random float between 0 and 1
	float fRandNum = (float)rand() / (float)RAND_MAX;

	// If the number is over 3/4...
	if(fRandNum > 0.75f)
	{
		// ... change it so it's between 1/2 and 3/4
		fRandNum -= 0.25f;
	} // else
	// otherwise, if the number is below 1/4...
	else if(fRandNum < 0.25f)
	{
		// ... change it so it's between 1/4 and 1/2
		fRandNum += 0.25f;
	} // else if

	// Gives a number between 0 and 1
	float fRandDirection = ((float)rand() / (float)RAND_MAX);
	int iXDirection;
	// If the random number is above 0.5 ...
	if(fRandDirection > 0.5)
	{
		// ... set the x direction to the right
		iXDirection = 1;
	} // if
	// otherwise...
	else
	{
		// ... set the x direction to the left
		iXDirection = -1;
	} // else

	// Gives a number between 0 and 1
	fRandDirection = ((float)rand() / (float)RAND_MAX);
	int iYDirection;
	// If the random number is above 0.5 ...
	if(fRandDirection > 0.5)
	{
		// ... set the y dirction to down
		iYDirection = 1;
	} // if
	// otherwise ...
	else
	{
		// ... set the y direction to up
		iYDirection = -1;
	} // else

	// Store the direction factor
	m_fXFactor = (fRandNum) * iXDirection;
	m_fYFactor = (1.0f - fRandNum) * iYDirection;
} // InitializeDirection